package com.smile.cloud.ossConfig.blob.impl;


import com.smile.cloud.ossConfig.FileUtils;
import com.smile.cloud.ossConfig.blob.BlobStorage;
import com.smile.cloud.ossConfig.oss.OssClient;
import com.smile.cloud.ossConfig.oss.model.OssObjectListResult;
import com.smile.cloud.ossConfig.oss.model.OssObjectResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

@Component
public class OssBlobStorage implements BlobStorage {
    @Value("${aliyun.oss.bucketName}")
    private String storageBucketName;
    @Autowired
    private OssClient ossClient;

    @Override
    public void create(final byte[] dataBytes, final String storeDir, final String fileName) throws Exception {
        if (dataBytes != null && dataBytes.length > 0) {
            final ByteArrayInputStream bis = new ByteArrayInputStream(dataBytes);
            try {
                this.ossClient.putObject(this.storageBucketName, FileUtils.concat(new String[]{storeDir, fileName}), (InputStream) bis);
            } finally {
                bis.close();
            }
        }
    }

    @Override
    public void create(final InputStream fileStream, final String storeDir, final String fileName) throws Exception {
        if (fileStream != null && fileStream.available() > 0) {
            this.ossClient.putObject(this.storageBucketName, FileUtils.concat(new String[]{storeDir, fileName}), fileStream);
        }
    }


    @Override
    public byte[] fetch(final String filePath) throws Exception {
        final OssObjectResult ossObject = this.ossClient.getObject(this.storageBucketName, filePath);
        final InputStream inStream = ossObject.getContent();
        if (inStream != null) {
            final ByteArrayOutputStream baos = new ByteArrayOutputStream();
            try {
                final byte[] byteChunk = new byte[4096];
                int n;
                while ((n = inStream.read(byteChunk)) > 0) {
                    baos.write(byteChunk, 0, n);
                }
                return baos.toByteArray();
            } finally {
                inStream.close();
                baos.close();
            }
        }
        return null;
    }

    @Override
    public void copy(final String srcFilePath, final String destFilePath) throws Exception {
        this.ossClient.copyObject(this.storageBucketName, srcFilePath, this.storageBucketName, destFilePath);
    }

    @Override
    public void move(final String srcFilePath, final String destFilePath) throws Exception {
        this.ossClient.copyObject(this.storageBucketName, srcFilePath, this.storageBucketName, destFilePath);
        this.ossClient.deleteObject(this.storageBucketName, srcFilePath);
    }

    @Override
    public void delete(final String filePath) throws Exception {
        this.ossClient.deleteObject(this.storageBucketName, filePath);
    }

    @Override
    public void deleteFolder(String folderPath) throws Exception {
        if (folderPath != null && !folderPath.isEmpty()) {
            if (!folderPath.endsWith("/")) {
                folderPath += "/";
            }
            OssObjectListResult listingResult = null;
            do {
                listingResult = this.ossClient.listObjects(this.storageBucketName, folderPath);
                if (listingResult.getObjectSummaries().size() > 0) {
                    final List<String> keys = new ArrayList<String>();
                    listingResult.getObjectSummaries().forEach(obj -> keys.add(obj.getKey()));
                    this.ossClient.deleteObjects(this.storageBucketName, (List) keys);
                }
            } while (listingResult.getObjectSummaries().size() != 0);
        }
    }
}
